#include <ltCmdList.h>
#include <crcCalc.h>
#include <hexstr.h>
const char *LT_PTC_SUB_VERSION = "LTPT-STD-V1.1.2407131959";

// =============command rwSn(write or read serial number) begin=====================
void ltCmdFuncOvtSnd_rwSn(ltCmdStcSnd_rwSn *idt)
{
    idt = NULL;
}
void ltCmdFuncOvtResp_rwSn(ltCmdStcResp_rwSn *odt)
{
    odt = NULL;
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFuncSubDo_rwSn(ltCmdUnion_rwSn *iodt, ltPtcParseStc *ptcptr)
{
    if (memcmp(parmNormIstc.sn, LT_CMD_DEFAULT_SN, LT_CMD_SN_MAX_SIZE) == 0)
    {
        logHexBufStr("sub cfg sn ok, my sn", parmNormIstc.sn, sizeof(parmNormIstc.sn));
        logHexBufStr("sub cfg sn ok, cfg sn", iodt->idt.wSn, sizeof(iodt->idt.wSn));
        memcpy(parmNormIstc.sn, iodt->idt.wSn, LT_CMD_SN_MAX_SIZE);
        // save param
        parmNormSave();
    }
    else
    {
        logHexBufStr("sub cfg sn fail, my sn", parmNormIstc.sn, sizeof(parmNormIstc.sn));
        logHexBufStr("sub cfg sn fail, cfg sn", iodt->idt.wSn, sizeof(iodt->idt.wSn));
    }
    memcpy(iodt->odt.rSn, parmNormIstc.sn, LT_CMD_SN_MAX_SIZE);
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFuncHostPack_rwSn(ltPtcParseStc *ptcptr, int packAddr, int packCrypt, ltCmdStcSnd_rwSn *packDt)
{
    ltCmdStcSnd_rwSn *tmpdata = (ltCmdStcSnd_rwSn *)ltPtcGetDataPtrV1(ptcptr);
    memcpy(tmpdata, packDt, sizeof(ltCmdStcSnd_rwSn));
    memcpy(ptcptr->hostSndInf, packDt->wSn, sizeof(tmpdata->wSn));
    // packCrypt not use
    packCrypt = ltPtcCrypte_None;
    return ltPtcHostPackCommV1(ptcptr, packAddr, packCrypt, ltCmdEnum_rwSn, sizeof(ltCmdStcSnd_rwSn));
}
int ltCmdFuncHostDoResp_rwSn(ltCmdStcResp_rwSn *odt, ltPtcParseStc *ptcptr)
{
    // logDebugHexBuf(odt->rSn, sizeof(odt->rSn));
    if (memcmp(ptcptr->hostSndInf, odt->rSn, sizeof(odt->rSn)) != 0)
    {
        logHexBufStr("host cfg sn fail, cfg sn", ptcptr->hostSndInf, sizeof(ptcptr->hostSndInf));
        logHexBufStr("host cfg sn fail, sub sn", odt->rSn, sizeof(odt->rSn));
    }
    else
    {
        logHexBufStr("host cfg sn ok, cfg sn", ptcptr->hostSndInf, sizeof(ptcptr->hostSndInf));
        logHexBufStr("host cfg sn ok, sub sn", odt->rSn, sizeof(odt->rSn));
    }
    return 1;
}
#endif
// =============command rwSn(write or read serial number) begin=====================

// =============command rwAddr(write or read address) begin=====================
void ltCmdFuncOvtSnd_rwAddr(ltCmdStcSnd_rwAddr *idt)
{
    idt = NULL;
}
void ltCmdFuncOvtResp_rwAddr(ltCmdStcResp_rwAddr *odt)
{
    odt = NULL;
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFuncSubDo_rwAddr(ltCmdUnion_rwAddr *iodt, ltPtcParseStc *ptcptr)
{
    if (memcmp(parmNormIstc.sn, iodt->idt.cfgSn, LT_CMD_SN_MAX_SIZE))
    {
        ptcptr->subRespStatFlag = ltPtcCmdResp_NotSndBack;
        return;
    }
    logdebug("sub cfg add:my=%d,set=%d", parmNormIstc.addr485, iodt->idt.wAddr);
    if (iodt->idt.rwflag)
    {
        parmNormIstc.addr485 = iodt->idt.wAddr;
        // save param
        parmNormSave();
    }
    iodt->odt.rAddr = parmNormIstc.addr485;
    // ltPtcSetAddrV1(ptcptr, parmNormIstc.addr485);
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFuncHostPack_rwAddr(ltPtcParseStc *ptcptr, int packAddr, int packCrypt, ltCmdStcSnd_rwAddr *packDt)
{
    ltCmdStcSnd_rwAddr *tmpdata = (ltCmdStcSnd_rwAddr *)ltPtcGetDataPtrV1(ptcptr);
    memcpy(tmpdata, packDt, sizeof(ltCmdStcSnd_rwAddr));
    ptcptr->hostSndInf[0] = packDt->wAddr;
    packCrypt = 0; // packCrypt not use.
    return ltPtcHostPackCommV1(ptcptr, packAddr, packCrypt, ltCmdEnum_rwAddr, sizeof(ltCmdStcSnd_rwAddr));
}
int ltCmdFuncHostDoResp_rwAddr(ltCmdStcResp_rwAddr *odt, ltPtcParseStc *ptcptr)
{
    if (ptcptr->hostSndInf[0] != odt->rAddr)
    {
        logerror("host set addr error:%d!=%d", ptcptr->hostSndInf[0], odt->rAddr);
        return -1;
    }
    else
    {
        logdebug("host set addr ok:%d=%d", ptcptr->hostSndInf[0], odt->rAddr);
    }
    return 1;
}
#endif
// =============command rwAddr(write or read address) end======================

// =============command getInf begin=====================
void ltCmdFuncOvtSnd_getInf(ltCmdStcSnd_getInf *idt)
{
    idt = NULL;
}
void ltCmdFuncOvtResp_getInf(ltCmdStcResp_getInf *odt)
{
    odt->dlgcrc = ovtBigSys16(odt->dlgcrc);
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFuncSubDo_getInf(ltCmdUnion_getInf *iodt, ltPtcParseStc *ptcptr)
{
#if LT_PTC_CMD_USE_CRYPTE
    // in, get inform command will set dialog key, so need crypte.
    if (ltPtcGetCrypteV1(ptcptr) != ltPtcCrypte_Sm4Pre)
    {
        logerror("");
        ptcptr->subRespStatFlag = ltPtcCmdResp_NdCrypt;
        return;
    }
    memcpy(ptcptr->ltPtcKeyDlg, iodt->idt.dlgKey, sizeof(iodt->idt.dlgKey));
    // out
    iodt->odt.dlgcrc = calcHashCrc16((const uint8_t *)ptcptr->ltPtcKeyDlg, sizeof(ptcptr->ltPtcKeyDlg));
#endif
    memset(iodt->odt.rvers, 0, sizeof(iodt->odt.rvers));
    memcpypro(iodt->odt.rvers, sizeof(iodt->odt.rvers), LT_PTC_SUB_VERSION, strlen(LT_PTC_SUB_VERSION));
    memcpy(iodt->odt.rsn, parmNormIstc.sn, LT_CMD_SN_MAX_SIZE);
    // response no need encrypte, there just for check.
#if LT_PTC_CMD_USE_CRYPTE
    ptcptr->subRespCrypteHostAddr = ltPtcCrypte_Sm4Pre;
#endif
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFuncHostPack_getInf(ltPtcParseStc *ptcptr, int packAddr, int packCrypt, ltCmdStcSnd_getInf *packDt)
{
#if LT_PTC_CMD_USE_CRYPTE
    ltCmdStcSnd_getInf *tmpdata = (ltCmdStcSnd_getInf *)ltPtcGetDataPtrV1(ptcptr);
    memcpy(tmpdata, packDt, sizeof(ltCmdStcSnd_getInf));
    memcpy(ptcptr->ltPtcKeyDlg, packDt->dlgKey, sizeof(ptcptr->ltPtcKeyDlg));
    *((uint16_t *)(ptcptr->hostSndInf)) = calcHashCrc16((const uint8_t *)tmpdata->dlgKey, sizeof(tmpdata->dlgKey));
    packCrypt = ltPtcCrypte_Sm4Pre; // packCrypt not use
#else
    packCrypt = ltPtcCrypte_None; // packCrypt not use
#endif
    return ltPtcHostPackCommV1(ptcptr, packAddr, packCrypt, ltCmdEnum_getInf, sizeof(ltCmdStcSnd_getInf));
}
int ltCmdFuncHostDoResp_getInf(ltCmdStcResp_getInf *odt, ltPtcParseStc *ptcptr)
{
#if LT_PTC_CMD_USE_CRYPTE
    if (ltPtcGetCrypteV1(ptcptr) != ltPtcCrypte_Sm4Pre)
    {
        logerror("host get info crypte error:%d", ltPtcGetCrypteV1(ptcptr));
        return -1;
    }
    logdebug("%d", odt->dlgcrc);
    if (*((uint16_t *)(ptcptr->hostSndInf)) != odt->dlgcrc)
    {
        logerror("host get info dkey crc error:%d!=%d", *((uint16_t *)(ptcptr->hostSndInf)), odt->dlgcrc);
        return -1;
    }
#endif
    logdebug("host get sub[%d] info ok! vers: %s", ltPtcGetAddrV1(ptcptr), odt->rvers);
    logHexBufStr("host get info sn", odt->rsn, sizeof(odt->rsn));
    return 1;
}
#endif
// =============command getInf end======================

// =============command heartBeat begin=====================
void ltCmdFuncOvtSnd_heartBeat(ltCmdStcSnd_heartBeat *idt)
{
    idt = NULL;
}
void ltCmdFuncOvtResp_heartBeat(ltCmdStcResp_heartBeat *odt)
{
    odt = NULL;
}
#if LT_PTC_CMD_SUB_ENABLE
void ltCmdFuncSubDo_heartBeat(ltCmdUnion_heartBeat *iodt, ltPtcParseStc *ptcptr)
{
    // in
    logdebug("sub rcv heartbeat:%s", iodt->idt.resvSnd);
    // out
    strcpy(iodt->odt.resvResp, "heartsub");
    // lcoPtr->subRespStatFlag = ltPtcCmdResp_OK;
    ptcptr->subRespCrypteHostAddr = ltPtcCrypte_Sm4Dlg;
    ptcptr->subRespSizeHostCmdId = sizeof(iodt->odt);
    return;
}
#endif
#if LT_PTC_CMD_HOST_ENABLE
int ltCmdFuncHostPack_heartBeat(ltPtcParseStc *ptcptr, int packAddr, int packCrypt, ltCmdStcSnd_heartBeat *packDt)
{
    ltCmdStcSnd_heartBeat *tmpdata = (ltCmdStcSnd_heartBeat *)ltPtcGetDataPtrV1(ptcptr);
    memcpy(tmpdata, packDt, sizeof(ltCmdStcSnd_heartBeat));
    packCrypt = ltPtcCrypte_Sm4Dlg; // packCrypt not use
    return ltPtcHostPackCommV1(ptcptr, packAddr, packCrypt, ltCmdEnum_heartBeat, sizeof(ltCmdStcSnd_heartBeat));
}
int ltCmdFuncHostDoResp_heartBeat(ltCmdStcResp_heartBeat *odt, ltPtcParseStc *ptcptr)
{
    logdebug("host rcv heart: %s", odt->resvResp);
    return 1;
}
#endif
// =============command heartBeat end======================

#if LT_PTC_CMD_SUB_ENABLE
#define SWITH_SUB_CMD_ID_FUNC(cmdname)                                                       \
    case ltCmdEnum_##cmdname:                                                                \
    {                                                                                        \
        ltCmdFuncOvtSnd_##cmdname((ltCmdStcSnd_##cmdname *)ltPtcGetDataPtrV1(ptcptr));       \
        ltCmdFuncSubDo_##cmdname((ltCmdUnion_##cmdname *)ltPtcGetDataPtrV1(ptcptr), ptcptr); \
        ltCmdFuncOvtResp_##cmdname((ltCmdStcResp_##cmdname *)ltPtcGetDataPtrV1(ptcptr));     \
        break;                                                                               \
    }
void ltCmdSubDealByID(ltPtcParseStc *ptcptr)
{
    switch (ltPtcGetCmdIdV1(ptcptr))
    {
        SWITH_SUB_CMD_ID_FUNC(rwSn);
        SWITH_SUB_CMD_ID_FUNC(rwAddr);
        SWITH_SUB_CMD_ID_FUNC(getInf);
        SWITH_SUB_CMD_ID_FUNC(heartBeat);
    default:
    {
        logerror("%d", ltPtcGetCmdIdV1(ptcptr));
        break;
    }
    }
}
#endif

#if LT_PTC_CMD_HOST_ENABLE
#define SWITH_HOST_CMD_ID_FUNC(cmdname)                                                                    \
    case ltCmdEnumDef(cmdname):                                                                            \
    {                                                                                                      \
        ltCmdFuncOvtResp_##cmdname((ltCmdStcResp_##cmdname *)ltPtcGetDataPtrV1(ptcptr));                   \
        return ltCmdFuncHostDoResp_##cmdname((ltCmdStcResp_##cmdname *)ltPtcGetDataPtrV1(ptcptr), ptcptr); \
    }
int ltCmdHostDealByID(ltPtcParseStc *ptcptr)
{
    switch (ltPtcGetCmdIdV1(ptcptr))
    {
        SWITH_HOST_CMD_ID_FUNC(rwSn);
        SWITH_HOST_CMD_ID_FUNC(rwAddr);
        SWITH_HOST_CMD_ID_FUNC(getInf);
        SWITH_HOST_CMD_ID_FUNC(heartBeat);
    default:
    {
        logerror("%d", ltPtcGetCmdIdV1(ptcptr));
        break;
    }
    }
    return 0;
}
#endif
